#include "Clerc.h"

#include <algorithm>
#include <ATL.h>

using namespace std;
using namespace boost::assign;

const unsigned int Clerc::nbr_comp = 108;

const unsigned int Clerc::nbr_restric = 20;

/**
 * Les noms des sphères sont accentuées "à la LaTeX", afin de
 * simplifier la gestion des noms de dossiers.
 */
const vector<ListComp> Clerc::Comp = list_of
  (ListComp("Amélioration de la classe d'armure"           , 15))
  (ListComp("Arme symbolique"                              ,  5))
  (ListComp("Bonus au JS contre drain d'énergie"           ,  5))
  (ListComp("Bonus au PV de guerrier"                      , 15))
  (ListComp("Changement de forme"                          ,  0, 100, &ChgtForme))
  (ListComp("Combat à mains nues"                          , 15))
  (ListComp("Communication"                                , 10))
  (ListComp("Compétences diverses de combattant"           ,  5))
  (ListComp("Compétences diverses de magicien"             ,  5))
  (ListComp("Compétences diverses de roublard"             ,  5))
  (ListComp("Connaissance des alignements"                 , 15))
  (ListComp("Contrôle des esprits"                         , 25, 200, &CtrlEsprit))
  (ListComp("Dés de vie à 1d10"                            , 10))
  (ListComp("Détection des morts-vivants"                  , 10))
  (ListComp("Détection du mal"                             , 10))
  (ListComp("Durée de sorts accrue (1 sphère)"             , 10))
  (ListComp("Durée de sorts accrue (toutes)"               , 15))
  (ListComp("Empathie avec les animaux"                    , 10))
  (ListComp("Guérisseur expert"                            , 10))
  (ListComp("Identification des plantes et animaux (niv 8)",  5))
  (ListComp("Identification des plantes et animaux (niv 3)",  8))
  (ListComp("Immunité à la magie"                          , 15))
  (ListComp("Immunité aux charmes"                         ,  0, 300, &ImmuCharme))
  (ListComp("Immunité aux maladies naturelles"             , 10))
  (ListComp("Imposition des mains"                         , 10))
  (ListComp("Incantation rapide"                           ,  5))
  (ListComp("Inspiration (+1)"                             ,  5))
  (ListComp("Inspiration (+2)"                             , 10))
  (ListComp("Langage secret"                               ,  5))
  (ListComp("Passage sans traces (niv 3)"                  ,  5))
  (ListComp("Passage sans traces (niv 1)"                  ,  7))
  (ListComp("Pouvoir divin"                                , 10, 400, &PouvDivins))
  (ListComp("Prêtre combattant"                            , 20))
  (ListComp("Purification de l'eau"                        ,  5))
  (ListComp("Repousser les morts-vivants"                  , 15))
  (ListComp("Résistance au drain d'énergie"                , 15))
  (ListComp("Résistance à l'électricité"                   ,  7))
  (ListComp("Résistance au feu"                            ,  7))
  (ListComp("Résistance au froid"                          ,  5))
  (ListComp("Sélection d'armes étendues"                   , 10))
  (ListComp("Suivants (niv 8)"                             ,  5))
  (ListComp("Suivants (niv 1)"                             , 10))
  (ListComp("TAc0 de guerrier"                             , 20))
  (ListComp("Talents de voleur"                            ,  0))
  // compétences -> 41
  (ListComp("G\\'en\\'erale (min)"                         ,  3))
  (ListComp("Animale (min)"                                ,  5))
  (ListComp("Astrale (min)"                                ,  3))
  (ListComp("Chaos (min)"                                  ,  5))
  (ListComp("Charme (min)"                                 ,  5))
  (ListComp("Climat (min)"                                 ,  3))
  (ListComp("Combat (min)"                                 ,  5))
  (ListComp("Conjuration (min)"                            ,  5))
  (ListComp("Cr\\'eation (min)"                            ,  5))
  (ListComp("Divination (min)"                             ,  5))
  (ListComp("El\\'ementaire (min)"                         ,  8))
  (ListComp("Air (min)"                                    ,  2))
  (ListComp("Eau (min)"                                    ,  2))
  (ListComp("Feu (min)"                                    ,  3))
  (ListComp("Terre (min)"                                  ,  3))
  (ListComp("Garde (min)"                                  ,  3))
  (ListComp("Guerre (min)"                                 ,  3))
  (ListComp("Loi (min)"                                    ,  5))
  (ListComp("N\\'ecromancie (min)"                         ,  5))
  (ListComp("Nombres (min)"                                ,  5))
  (ListComp("Pens\\'ee (min)"                              ,  5))
  (ListComp("Protection (min)"                             ,  5))
  (ListComp("Soin (min)"                                   ,  5))
  (ListComp("Soleil (min)"                                 ,  3))
  (ListComp("Temps (min)"                                  ,  5))
  (ListComp("V\\'eg\\'etale (min)"                         ,  5))
  (ListComp("Vigilance (min)"                              ,  5))
  (ListComp("Voyageur (min)"                               ,  3))
  // sphères mineures -> 68
  (ListComp("G\\'en\\'erale (maj)"                         ,  5))
  (ListComp("Animale (maj)"                                , 10))
  (ListComp("Astrale (maj)"                                ,  6))
  (ListComp("Chaos (maj)"                                  ,  8))
  (ListComp("Charme (maj)"                                 , 10))
  (ListComp("Climat (maj)"                                 , 10))
  (ListComp("Combat (maj)"                                 , 10))
  (ListComp("Conjuration (maj)"                            , 10))
  (ListComp("Cr\\'eation (maj)"                            , 10))
  (ListComp("Divination (maj)"                             , 10))
  (ListComp("El\\'ementaire (maj)"                         , 20))
  (ListComp("Air (maj)"                                    ,  5))
  (ListComp("Eau (maj)"                                    ,  5))
  (ListComp("Feu (maj)"                                    ,  8))
  (ListComp("Terre (maj)"                                  ,  8))
  (ListComp("Garde (maj)"                                  ,  5))
  (ListComp("Guerre (maj)"                                 ,  5))
  (ListComp("Loi (maj)"                                    ,  8))
  (ListComp("N\\'ecromancie (maj)"                         , 10))
  (ListComp("Nombres (maj)"                                , 10))
  (ListComp("Pens\\'ee (maj)"                              , 10))
  (ListComp("Protection (maj)"                             , 10))
  (ListComp("Soin (maj)"                                   , 10))
  (ListComp("Soleil (maj)"                                 ,  5))
  (ListComp("Temps (maj)"                                  , 10))
  (ListComp("V\\'eg\\'etale (maj)"                         , 10))
  (ListComp("Vigilance (maj)"                              , 10))
  (ListComp("Voyageur (maj)"                               ,  5))
  (ListComp("Abjuration (mage)"                            , 25))
  (ListComp("Alt\\'eration (mage)"                         , 25))
  (ListComp("Conjuration - Convocation (mage)"             , 25))
  (ListComp("Enchantement - Charme (mage)"                 , 25))
  (ListComp("Divination (mage)"                            , 25))
  (ListComp("Illusion - Fantasme (mage)"                   , 25))
  (ListComp("Invocation - Evocation (mage)"                , 25))
  (ListComp("N\\'ecromancie (mage)"                        , 25));
  // sphères majeures -> 105

const vector<ListComp> Clerc::Restric = list_of
  (ListComp("Cérémonial"                                  ,  5))
  (ListComp("Choix des armes restreint"                   ,  5))
  (ListComp("Choix de sorts restreint"                    ,  5))
  (ListComp("Dés de vie à 1d6"                            , 10))
  (ListComp("Dés de vie à 1d4"                            , 20))
  (ListComp("Difficultés de mémorisation"                 ,  5))
  (ListComp("Fanatisme"                                   ,  5))
  (ListComp("Incantation longue"                          ,  5))
  (ListComp("Lim : potions, huiles et parchemins"         ,  5))
  (ListComp("Lim : anneau, de bâton, bâtonnet et baguette",  5))
  (ListComp("Lim : armes et armures magiques"             ,  5))
  (ListComp("Limitation à la maille"                      ,  5))
  (ListComp("Limitation au cuir clouté"                   , 10))
  (ListComp("Manque de discrétion"                        ,  5))
  (ListComp("Pas d'armes"                                 , 15))
  (ListComp("Pas d'armure"                                , 15))
  (ListComp("Progression ralentie"                        , 15))
  (ListComp("Sorts dangereux"                             , 10))
  (ListComp("Tabou"                                       ,  2))
  (ListComp("Talisman"                                    ,  8));

const vector< Prerequis > Clerc::Limites = list_of
  (Prerequis(4, 9));

const set< string > Clerc::RacesAdmises = list_of
  ( "Humain" ) ( "Demi-Elfe" ) ( "Demi-Ogre" ) ( "Demi-Orque" )
  ( "Elfe" ) ( "Gnome" ) ( "Hobbit" ) ( "Nain" );

const vector< ListComp > Clerc::ChgtForme = list_of
  (ListComp("Normal - niv 7", 15))
  (ListComp("Dès niv 6", 17)) (ListComp("Dès niv 5", 19))
  (ListComp("Dès niv 4", 21)) (ListComp("Dès niv 3", 23))
  (ListComp("Dès niv 2", 25)) (ListComp("Dès niv 1", 27));

const vector< ListComp > Clerc::CtrlEsprit = list_of
  (ListComp("Esprits animaux", 5))
  (ListComp("Esprits des morts", 5)) 
  (ListComp("Esprits de la nature", 5));

const vector< ListComp > Clerc::ImmuCharme =  list_of
  (ListComp("Créatures extraplanaires", 5))
  (ListComp("Créatures sylvestres", 5))
  (ListComp("Créatures végétales", 5))
  (ListComp("Magiciens", 5))
  (ListComp("Morts-vivants", 5))
  (ListComp("Dès niv 6", 1)) (ListComp("Dès niv 5", 2)) (ListComp("Dès niv 4", 3))
  (ListComp("Dès niv 3", 4)) (ListComp("Dès niv 2", 5)) (ListComp("Dès niv 1", 6));

const vector< ListComp > Clerc::PouvDivins = list_of
  (ListComp("Sort de prêtre niv 1", 1)) (ListComp("Sort de prêtre niv 2", 2))
  (ListComp("Sort de prêtre niv 3", 3)) (ListComp("Sort de prêtre niv 4", 4)) 
  (ListComp("Sort de prêtre niv 5", 5))
  (ListComp("Sort de mage niv 1", 2)) (ListComp("Sort de mage niv 2", 4))
  (ListComp("Sort de mage niv 3", 6)) (ListComp("Sort de mage niv 4", 8)) 
  (ListComp("Sort de mage niv 5", 10)) 
  (ListComp("1x / jour", 5)) (ListComp("2x / jour", 6)) (ListComp("3x / jour", 7))
  (ListComp("Permanent", 10));

/** Constructeur usuel.
 * Permet la construction d'un clerc de A à Z, càd on détermine ici
 * les restrictions, puis les compétences.
 * @param xp le nombre de pts d'expérience du Clerc.
 * @param trait les traits du Clerc, le 7ème contient le score de
 * force exceptionnel, fixé à 0 si non applicable.
 * @param PP nombre de points de personnage (PP) à disposition pour la
 * céation du Clerc.
 * @param race nom de la race du personnage.
 */
Clerc::Clerc(unsigned int xp, unsigned int trait[7], unsigned int& PP,
	     const string& race)
  : Classe(xp, trait, Pretres, race)
{
  Type_classe = "Clerc";
  PP += 120;

  ptrComp         = &Comp;
  ptrRes          = &Restric;
  ptrNbrComp      = &nbr_comp;
  ptrNbrRes       = &nbr_restric;
  ptrTraitsRequis = &Limites;
  ptrRacesAdmises = &RacesAdmises;

  blank() << "********************************************************" << endreq;
  blank() << "Création d'un clerc" << endl << endreq;

  construitClasse( PP );

//   unsigned int nbr(0),  pps(0);

//   for (unsigned int i(0); i<nbr_restric; i++)
//     {
//       if (Restric[i].Cout != 0)
// 	blank() << i+1 << ' ' << afficheAccent(Restric[i].Comp)
// 		    << " (" << Restric[i].Cout << " pp)" << endreq;
//       else
// 	blank() << i+1 << ' ' << afficheAccent(Restric[i].Comp)
// 		    << " cout variable" << endreq;	
//     }
//   blank() << nbr_restric+1 << " Aucune" << endreq;
//   blank() << "Choisir les restrictions" << endreq;

//   bool test(true), deja_pris, encore(false);
//   unsigned int save_PP(PP);

//   do
//     {
//       do
// 	{
// 	  nbr = demanderUnsignedBorne("Choisir les restrictions ", 1,
// 					nbr_restric + 1);
	  
// 	  if (nbr != nbr_restric+1)
// 	    {
// 	      if (Restric[nbr-1].Cout == 0)
// 		{
// 		  deja_pris = safePushBack(&Comp_classe, 104 + nbr);
// 		  if (deja_pris)
// 		    warning() << "Déjà sélectionné" << endreq;
// 		  else
// 		    {
// 		      Comp_classe.push_back(104+nbr);
// 		      pps = demanderUnsigned("Entrer les pp obtenus : ");
// 		      PP += pps;
// 		      blank() << "Restriction choisie : "
// 				  << afficheAccent(Restric[nbr-1].Comp) << endreq;
// 		    }
// 		}
// 	      else
// 		{
// 		  deja_pris = safePushBack(&Comp_classe, 104 + nbr);
// 		  if (deja_pris)
// 		    warning() << "Déjà sélectionné" << endreq;
// 		  else
// 		    {
// 		      Comp_classe.push_back(104+nbr);
// 		      PP += Restric[nbr-1].Cout;
// 		      blank() << "Restriction choisie : "
// 				  << afficheAccent(Restric[nbr-1].Comp) << endreq;
// 		    }
// 		}
// 	    }
// 	  else
// 	    test = false;
// 	}
//       while(test);

//       afficheCompetences();
//       blank() << endl <<  "1 pour continuer, 2 pour recommencer" << endreq;
//       nbr = demanderUnsignedBorne("Choix ", 1, 2);
//       if (nbr == 2)
// 	{
// 	  PP = save_PP;
// 	  Comp_classe.clear();
// 	  test = true;
// 	  encore = true;
// 	  blank() << endreq;
// 	}
//       else
// 	encore = false;
//     }
//   while(encore);
      
//   blank() << "Tu as " << PP << " pp à dépenser" << endreq;
//   save_PP = PP;

//   for (unsigned int i(0); i<nbr_comp; i++)
//     {
//       if (Comp[i].Cout != 0)
// 	blank() << i+1 << ' ' << afficheAccent(Comp[i].Comp)
// 		    << " (" << Comp[i].Cout << " pp)" << endreq;
//       else
// 	blank() << i+1 << ' ' << afficheAccent(Comp[i].Comp)
// 		    << " (cout variable)" << endreq;	
//     }
//   blank() << nbr_comp+1 << " Aucune" << endreq;
//   blank() << "Choisir les compétences de classe" << endreq;

//   test = true;

//   do
//     {
//       do
// 	{
// 	  nbr = demanderUnsignedBorne("("+ecrireString(PP)+" restants) ", 1,
// 					nbr_comp + 1);
	  
// 	  if (nbr!=nbr_comp+1)
// 	    {
// 	      deja_pris = safePushBack(&Comp_classe, nbr - 1);
// 	      if (deja_pris)
// 		warning() << "Déjà sélectionné" << endreq;
// 	      else
// 		{
// 		  if (Comp[nbr-1].Cout == 0)
// 		    {
// 		      pps = demanderUnsigned("Entrez le coût : ");
// 		    }
// 		  else
// 		    pps = Comp[nbr-1].Cout;
// 		  if (PP >= pps)
// 		    {
// 		      Comp_classe.push_back(nbr-1);
// 		      PP -= Comp[nbr-1].Cout;
// 		      blank() << "Compétence choisie : " 
// 				  << afficheAccent(Comp[nbr-1].Comp) << endreq;
// 		      // tester si c'est les compétences supplémentaires
// 		      if (nbr == 40)
// 			TC.push_back(Roublards);
// 		    }
// 		  else
// 		    blank() << "Pas assez de pp" << endreq;
// 		}
// 	    }
// 	  else
// 	    test = false;
// 	}
//       while(test);

//       afficheCompetences();
//       blank() << endl <<  "1 pour continuer, 2 pour recommencer" << endreq;
//       nbr = demanderUnsignedBorne("Choix ", 1, 2);
//       if (nbr == 2)
// 	{
// 	  PP = save_PP;
// 	  while(Comp_classe.back() < nbr_comp)
// 	    Comp_classe.pop_back();
// 	  test = true;
// 	  encore = true;
// 	  blank() << endreq;
// 	}
//       else
// 	encore = false;
//     }
//   while(encore);

  blank() << endl << setfill('*') << setw(56) << '*' << setfill(' ')
	      << endreq;
  calculNiveau();
  calculNivMag();
}

/** Constructeur simplifié.
 * Permet de construire un Clerc lors de la lecture d'un ficier xml.
 * @param xp le nombre de pts d'expérience du Clerc.
 * @param trait les traits du Clerc, le 7ème contient le score de
 * force exceptionnel, fixé à 0 si non applicable.
 * @param race nom de la race du personnage.
 */
Clerc::Clerc(unsigned int xp, unsigned int trait[7], const string& race)
  : Classe(xp, trait, Pretres, race)
{
  Type_classe = "Clerc";

  ptrComp         = &Comp;
  ptrRes          = &Restric;
  ptrNbrComp      = &nbr_comp;
  ptrNbrRes       = &nbr_restric;
  ptrTraitsRequis = &Limites;
  ptrRacesAdmises = &RacesAdmises;

  calculNiveau();
  calculNivMag();
}

/** Constructeur pour le mode graphique.
 * Permet de construire une instance de Clerc avec le contenu minimal,
 * le nombre de points d'expériences et les capacités étant
 * déterminées après la déclaration.
 *
 * @param trait les traits du Clerc, le 7ème contient le score de
 * force exceptionnel, fixé à 0 si non applicable.
 * @param UI contrôle, est présent pour des raisons historiques.
 * @param race nom de la race du personnage.
 */
Clerc::Clerc(unsigned int trait[7], const bool& UI, const string& race)
  : Classe(0, trait, Pretres, race)
{
  Type_classe = "Clerc";

  ptrComp         = &Comp;
  ptrRes          = &Restric;
  ptrNbrComp      = &nbr_comp;
  ptrNbrRes       = &nbr_restric;
  ptrTraitsRequis = &Limites;
  ptrRacesAdmises = &RacesAdmises;
  
  if (!UI)
    {
      error() << "Création du personnage impossible" << endreq;
      exit(1);
    }

  calculNiveau();
  calculNivMag();
}

Clerc::~Clerc()
{}

void Clerc::calculNiveau()
{
  if (XP < 13000)
    {
      unsigned int i;
      for (i = 0; i < 3; i++)
	{
	  if (XP < (unsigned int) 1500 * puissance(2, i))
	    break;
	}
      Niveau = i + 1;
    }
  else if (XP < 27500)
    Niveau = 5;
  else if (XP < 55000)
    Niveau = 6;
  else if (XP < 110000)
    Niveau = 7;
  else if (XP < 225000)
    Niveau = 8;
  else
      Niveau = (XP - 225000) / 225000 + 9;
}

// /**
//  * Il faut faire attention aux accents...
//  * @see afficheAccent
//  */
// void Clerc::afficher_stats(ostream& os)
// {
//   os << "Classe : Clerc" << endreq;
//   for (unsigned int i(0); i<6; i++)
//     os << Caracteristiques[i] << ' ' << Traits[i] << endreq;
//   for (unsigned int i(0); i<Comp_classe.size(); i++)
//     {
//       if (Comp_classe[i] >= nbr_comp)
// 	os << afficheAccent(Restric[Comp_classe[i]-nbr_comp].Comp)
// 		    << endreq;
//       else
// 	os << afficheAccent(Comp[Comp_classe[i]].Comp) << endreq;
//     }
// }

// void Clerc::appliquerModif(const string& type)
// {}

// void Clerc::augmenterTalents(const unsigned int& bonus, const bool& lvl_up)
// {}

void Clerc::getJS(unsigned int *tab) const
{
  Debug::empileNiveau( &fonction );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(fonction);
  *(tab + 0) = 10; // Paralysie, Poison ou Mort magique
  *(tab + 1) = 14; // Bâton, batonnet baguette
  *(tab + 2) = 13; // Pétrification ou Métamorphose
  *(tab + 3) = 16; // Souffles
  *(tab + 4) = 15; // Sorts

  debug() << "Niveau = " << Niveau << endreq;
  
  unsigned int cat;
  if (Niveau <= 3)
    cat = 0;
  else if (Niveau <= 6)
    cat = 1;
  else if (Niveau <= 9)
    cat = 3;
  else if (Niveau <= 12)
    cat = 4;
  else if (Niveau <= 15)
    cat = 5;
  else if (Niveau <= 18)
    cat = 6;
  else
    cat = 8;

  *(tab + 0) -= cat;
  *(tab + 1) -= cat;
  *(tab + 2) -= cat;
  *(tab + 3) -= cat;
  *(tab + 4) -= cat;
  Debug::depileNiveau();//dout.setLevel(etat_precedent);
}

/**
 * Si Classe::elementaire a la valeur DEBUG, la distinction Compétence /
 * Restriction est affichée.
 */
// string Clerc::getCompetence(const unsigned int& i) const
// {
//   Debug::empileNiveau( &elementaire );
//   //DebugLevelType etat_precedent(dout.getLevel());
//   //dout.setLevel(elementaire);
//   if (getComp(i) < nbr_comp)
//     {
//       debug() << "comp " << getComp(i) << " => comp" << endreq;
//       Debug::depileNiveau();//dout.setLevel(etat_precedent);
//       return Comp[getComp(i)].Comp;
//     }
//   else
//     {
//       debug() << "comp " << getComp(i) << " => res" << endreq;
//       Debug::depileNiveau();//dout.setLevel(etat_precedent);
//       return Restric[getComp(i)-nbr_comp].Comp;
//     }
// }

unsigned int Clerc::calculeTAc0() const
{
  unsigned int mod_niveau(2 * ((Niveau - 1) / 3));

  return 20 - mod_niveau;
}

void Clerc::calculNivMag()
{
  if (Niveau < 16)
    Niveau_mag = (Niveau + 1) / 2;
  else
    Niveau_mag = 7;
}

/**
 * Les sorts disponibles pour un Clerc sont donnés par son niveau et
 * les sphères auquelles il a accès.
 *
 * La variable Classe::fonction permet d'afficher :
 *
 * FUNC  : le nom du fichier qui va être écrit
 *
 * LINFO : la vérification que la compétence est bien une sphère, ou une
 * école de magie
 *
 * LFUNC : gestion des sphères élémentaires et des accents
 *
 * DEBUG : ouverture du fichier, 
 * 
 */
void Clerc::ecrireSorts(const string& nom_fichier, const bool& ecrase) const
{
  Debug::empileNiveau( &fonction );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(fonction);
  func() << "Clerc::ecrireSorts -> début" << endreq;
  ofstream sortie;
  string nom_complet, tmp;
  func() << "A écrire : " << nom_fichier << endreq;

  if (ecrase)
    /*
     * Ecrase l'éventuel contenu du fichier
     */
    {
      sortie.open(nom_fichier.c_str());
      debug() << "Ouverture                [ OK ]" << endreq;
    }
  else
    /*
     * Alors on ouvre le fichier de telle sorte à écrire à la suite
     */
    {
      sortie.open(nom_fichier.c_str(), ios::app);
      debug() << "Ouverture                [ OK ]" << endreq;
    }

  sortie << "\\section*{Sorts disponibles - Prêtre}" << endl;

  unsigned int *vec = new unsigned int[Niveau_mag];

  nbrSort(vec, Niveau_mag);

  sortie << "\\begin{center}" << endl 
	 << "\\begin{tabular*}{10cm}{@{\\extracolsep{\\fill}} l r}"
	 << endl << "\\multicolumn{2}{c}{Nombre de sorts par jour} \\\\"
	 << "\\hline \\\\ \\vspace{1mm}" << endl;
  for (unsigned int i(0); i < Niveau_mag; i++)
    sortie << "Niveau " << i+1 << " & " << *(vec + i) << " \\\\" << endl;
  sortie << "\\end{tabular*}" << endl << "\\end{center}" << endl;

  unsigned int taille(getCombien());
  size_t loc;
  bool sauter( false );

  for (unsigned int i(0); i < taille; i++)
    {
      if (getComp(i) > 2)
	{
	  /*
	   * Ne pas oublier le 'true', pour garder la syntaxe LaTeX !
	   * sinon on a les accents écrits "en dur" et on ne peut plus
	   * rien faire pour rattraper le coup!
	   */
	  tmp = getCompetence(i, sauter, true);
	  linfo() << "Check sphère : " << tmp << endreq;
	  loc = tmp.find(" (m", 0);
	  if (loc == string::npos)
	    {
	      lfunc() << "Pas une sphère..." << endreq;
	      continue;
	    }
	  tmp.replace(loc, 6, "");
	  loc = tmp.find("mentaire", 0);
	  if (loc != string::npos)
	    {
	      lfunc() << "Sphère Elémentaire..." << endreq;
	      continue;
	    }
	  
	  loc = tmp.find(")", 0);
	  if (loc != string::npos)
	    {
	      linfo() << "Ecole de magie" << endreq;
	      tmp = supprimeAccents(tmp);
	      loc = tmp.find(")", 0);
	      if (loc != string::npos)
		  tmp.replace(loc, 1, "");
	      tmp += "_mage";
	    }

	  for (unsigned int j(1); j <= Niveau_mag; j++)
	    {
	      if (getComp(i) < 68 && j > 3)
		/*
		 * Accès mineur => jusqu'au lvl 3 uniquement!
		 */
		break;
	      lfunc() << "accents loin " << supprimeAccents(tmp) << endreq;
	      sortie << "\\input{../../Sorts-clerc/" << supprimeAccents(tmp)
		     << "-"  << ecrireString(j) << ".inc.tex}" << endl;
	      
	    }
	
	}
    }
  //delete vec;
  sortie.close();
  func() << "Clerc::ecrireSorts -> fin" << endreq;
  Debug::depileNiveau();//dout.setLevel(etat_precedent);
}

void Clerc::nbrSort(unsigned int sorts[], const unsigned int& taille) const
{
  Debug::empileNiveau( &fonction );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(fonction);
  unsigned int i;
  unsigned int tmp[7];
  func() << "Taille = " << taille << endreq;

  for (i = 0; i < taille; i++)
    tmp[i] = 0;

  switch(Niveau)
    {
    case 1:
      tmp[0] = 1;
      break;
    case 2:
      tmp[0] = 2;
      break;
    case 3:
      tmp[0] = 2;
      tmp[1] = 1;
      break;
    case 4:
      tmp[0] = 3;
      tmp[1] = 2;
      break;
    case 5:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 1;
      break;
    case 6:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 2;
      break;
    case 7:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 2;
      tmp[3] = 1;
      break;
    case 8:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 3;
      tmp[3] = 2;
      break;
    case 9:
      tmp[0] = 4;
      tmp[1] = 4;
      tmp[2] = 3;
      tmp[3] = 2;
      tmp[4] = 1;
      break;
    case 10:
      tmp[0] = 4;
      tmp[1] = 4;
      tmp[2] = 3;
      tmp[3] = 3;
      tmp[4] = 2;
      break;
    case 11:
      tmp[0] = 5;
      tmp[1] = 4;
      tmp[2] = 4;
      tmp[3] = 3;
      tmp[4] = 2;
      if (Traits[4] >= 17)
      tmp[5] = 1;
      break;
    case 12:
      tmp[0] = 6;
      tmp[1] = 5;
      tmp[2] = 5;
      tmp[3] = 3;
      tmp[4] = 2;
      if (Traits[4] >= 17)
      tmp[5] = 2;
      break;
    case 13:
      tmp[0] = 6;
      tmp[1] = 6;
      tmp[2] = 6;
      tmp[3] = 4;
      tmp[4] = 2;
      if (Traits[4] >= 17)
      tmp[5] = 2;
      break;
    case 14:
      tmp[0] = 6;
      tmp[1] = 6;
      tmp[2] = 6;
      tmp[3] = 5;
      tmp[4] = 3;
      if (Traits[4] >= 17)
      tmp[5] = 2;
      if (Traits[4] >= 18)
      tmp[6] = 1;
      break;
    case 15:
      tmp[0] = 6;
      tmp[1] = 6;
      tmp[2] = 6;
      tmp[3] = 6;
      tmp[4] = 4;
      if (Traits[4] >= 17)
	tmp[5] = 2;
      if (Traits[4] >= 18)
	tmp[6] = 1;
      break;
    case 16:
      tmp[0] = 7;
      tmp[1] = 7;
      tmp[2] = 7;
      tmp[3] = 6;
      tmp[4] = 4;
      if (Traits[4] >= 17)
	tmp[5] = 3;
      if (Traits[4] >= 18)
	tmp[6] = 1;
      break;
    case 17:
      tmp[0] = 7;
      tmp[1] = 7;
      tmp[2] = 7;
      tmp[3] = 7;
      tmp[4] = 5;
      if (Traits[4] >= 17)
	tmp[5] = 3;
      if (Traits[4] >= 18)
	tmp[6] = 2;
      break;
    case 18:
      tmp[0] = 8;
      tmp[1] = 8;
      tmp[2] = 8;
      tmp[3] = 8;
      tmp[4] = 6;
      if (Traits[4] >= 17)
	tmp[5] = 4;
      if (Traits[4] >= 18)
	tmp[6] = 2;
      break;
    case 19:
      tmp[0] = 9;
      tmp[1] = 9;
      tmp[2] = 8;
      tmp[3] = 8;
      tmp[4] = 6;
      if (Traits[4] >= 17)
	tmp[5] = 4;
      if (Traits[4] >= 18)
	tmp[6] = 2;
      break;
    default:
      tmp[0] = 9;
      tmp[1] = 9;
      tmp[2] = 9;
      tmp[3] = 8;
      tmp[4] = 7;
      if (Traits[4] >= 17)
	tmp[5] = 5;
      if (Traits[4] >= 18)
	tmp[6] = 2;
      break;
    }

  for (i = 0; i < Niveau_mag; i++)
    sorts[i] = tmp[i];

  unsigned int compteur1(0), compteur2(0), compteur3(0), compteur4(0);

  if (Traits[4] >= 13 && Traits[4] < 18)
    {
      compteur1 = (Traits[4] - 11) / 2;
      compteur2 = (Traits[4] - 12) / 2;
    }
  else if (Traits[4] >= 18 && Traits[4] < 19)
    {
      compteur1 = Traits[4] - 14;
      compteur2 = Traits[4] - 16;
    }
  else if (Traits[4] >= 19 && Traits[4] < 23)
    {
      compteur1 = (Traits[4] + 1) / 2 - 6;
      compteur2 = Traits[4] / 2 - 6;
      compteur3 = Traits[4] - 18;
    }
  else
    {
      compteur1 = (Traits[4] + 1) / 2 - 6;
      compteur2 = Traits[4] / 2 - 6;
      compteur3 = Traits[4] - 19;
      compteur4 = 1;
    }

  for (i = 0; i < compteur1; i++)
    {
      if (i == Niveau_mag)
	break;
      sorts[i]++;
    }
  for (i = 0; i < compteur2; i++)
    {
      if (i == Niveau_mag)
	break;
      sorts[i]++;
    }
  for (i = 0; i < compteur3; i++)
    {
      if (i == Niveau_mag)
	break;
      sorts[i]++;
    }
  for (i = 0; i < compteur4; i++)
    {
      if (i == Niveau_mag)
	break;
      sorts[i]++;
    }

  Debug::depileNiveau();//dout.setLevel(etat_precedent);  
}

/**
 * Permet de gérer les compétences martiales, càd lesquelles sont accessibles
 * à quel coût.
 *
 * Un Clerc peut prendre un arme réservée au Clerc pour 3 pp, ou alors une
 * arme de Guerrier pour 4 pp.
 */
void Clerc::getPrixAcces(map<string, unsigned int>*& Map) const
{
  Debug::empileNiveau( &fonction );
  func() << "Clerc::getPrixAcces -> début" << endreq;

  ExtraireClef< string, unsigned int > extraitStr;
  vector< string > clefs( Map -> size() );
  EcrireElementConteneur< string > ecrireStr( &lfunc() );

  map<string, unsigned int>::const_iterator mapIt, mapBegin(Map -> begin()),
    mapEnd(Map -> end());
  
  transform( mapBegin, mapEnd, clefs.begin(), extraitStr );
  for_each( clefs.begin(), clefs.end(), ecrireStr );

//   for (mapIt = mapBegin; mapIt != mapEnd; mapIt++)
//        lfunc() << mapIt -> first << endreq;
 
  mapIt = Map -> find("Clerc");
  if ((mapIt != mapEnd && mapIt -> second > 3) || mapIt == mapEnd)
    Map -> operator[]("Clerc")    = 3;
  mapIt = Map -> find("Guerrier");
  if ((mapIt != mapEnd && mapIt -> second > 4) || mapIt == mapEnd)
    Map -> operator[]("Guerrier") = 4;
  
  func() << "Clerc::getPrixAccess -> fin" << endreq;
  Debug::depileNiveau();
}

bool Clerc::forceExceptionnelle() const
{
  return ( std::find( Comp_classe.begin(), Comp_classe.end(), 38 )
	   != Comp_classe.end() );  
}
